/*
 * 文件名：PayPost.java
 * 版权：Copyright by www.suyinchina.com
 * 描述：
 * 修改人：XYX
 * 修改时间：2014-4-16
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package com.caiyouxi.pay.payment.weixin.wxpay;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.DocumentException;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;


public class PayPost
{
    public static void main(String[] args)
        throws DocumentException, KeyManagementException, UnrecoverableKeyException,
        NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException
    {
//        System.out.println(wxPay("2830922223341233", "3223", 1.1, CommonUtil.CreateNoncestr()));
    }


    /**
     *
     * Description: Post SSL请求
     *
     * @param requestXML
     * @param instream
     * @return
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     * @throws KeyManagementException
     * @throws UnrecoverableKeyException
     * @throws KeyStoreException
     * @see
     */
    public static String post(String requestXML, String url)
        throws NoSuchAlgorithmException, CertificateException, IOException,
        KeyManagementException, UnrecoverableKeyException, KeyStoreException
    {
        requestXML = new String(requestXML.getBytes("ISO-8859-1"), "UTF-8");
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        FileInputStream instream = new FileInputStream(new File("D:/1264350301.p12"));

        ///data_dev1/u01/YDL/props/1264350301.p12
        try
        {
            keyStore.load(instream, "1264350301".toCharArray());
        }
        finally
        {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,
            "1264350301".toCharArray()).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
            new String[] {"TLSv1"}, null,
            SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        // SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] {"SSLv3"}, null, null);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        String result = "";
        try
        {
            HttpPost httpPost = new HttpPost(url);
            StringEntity reqEntity = new StringEntity(requestXML, "GBK"); //如果此处编码不对，可能导致客户端签名跟微信的签名不一致
            reqEntity.setContentEncoding("UTF-8");
            reqEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(reqEntity);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try
            {
                HttpEntity entity = response.getEntity();
                if (entity != null)
                {
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
                        entity.getContent(), "UTF-8"));
                    String text;
                    while ((text = bufferedReader.readLine()) != null)
                    {
                        result += text;
                    }
                }
                EntityUtils.consume(entity);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                response.close();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            httpclient.close();
        }
        return result;
    }

    HostnameVerifier hv = new HostnameVerifier()
    {
        public boolean verify(String urlHostName, SSLSession session)
        {
            System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                               + session.getPeerHost());
            return true;
        }
    };

    public static String postRequestUrl(String url, String param)
    {
        CloseableHttpClient httpclient = null;
        InputStream in = null;
        StringBuffer sb = new StringBuffer();
        try
        {
            httpclient = createHttpsClient();
            HttpPost post = new HttpPost(url);
            post.addHeader("Content-Type", "text/html;charset=UTF-8");
            post.setEntity(new StringEntity(param, "utf-8"));
            HttpResponse response = httpclient.execute(post);
            HttpEntity entity = response.getEntity();
            in = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
            String line = null;
            while ((line = reader.readLine()) != null)
            {
                sb.append(line);
            }
        }
        catch (Exception ex)
        {
            System.out.println("异常：" + ex.getMessage());
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
                if (httpclient != null)
                {
                    httpclient.close();
                }
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                System.out.println("异常：" + ex.getMessage());
            }
        }
        return sb.toString();
    }

    public static CloseableHttpClient createHttpsClient()
    {
        X509TrustManager x509mgr = new X509TrustManager()
        {
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException
            {}

            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException
            {}

            public java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }
        };
        SSLContext sslContext = null;
        try
        {
            sslContext = SSLContext.getInstance("TLS");
        }
        catch (NoSuchAlgorithmException e1)
        {
            e1.printStackTrace();
        }
        try
        {
            sslContext.init(null, new TrustManager[] {x509mgr}, null);
        }
        catch (KeyManagementException e)
        {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     * @throws UnsupportedEncodingException
     */
    public static String sendPost(String url, String param)
        throws UnsupportedEncodingException
    {
        //        //param = new String(param.getBytes("UTF-8"), "GBK");
        //        PrintWriter out = null;
        //        BufferedReader in = null;
        String result = "";
        //        try
        //        {
        //
        //            URL realUrl = new URL(url);
        //
        //            // 打开和URL之间的连接
        //            URLConnection conn = realUrl.openConnection();
        //            // 设置通用的请求属性
        //            conn.setRequestProperty("accept", "*/*");
        //            conn.setRequestProperty("connection", "Keep-Alive");
        //            conn.setRequestProperty("user-agent",
        //                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        //            // 发送POST请求必须设置如下两行
        //            conn.setDoOutput(true);
        //            conn.setDoInput(true);
        //            // 获取URLConnection对象对应的输出流
        //            out = new PrintWriter(conn.getOutputStream());
        //            // 发送请求参数
        //            out.print(param);
        //            // flush输出流的缓冲
        //            out.flush();
        //            // 定义BufferedReader输入流来读取URL的响应
        //            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        //            String line;
        //            while ((line = in.readLine()) != null)
        //            {
        //                result += line;
        //            }
        //            System.out.println(result);
        //        }
        //        catch (Exception e)
        //        {
        //            System.out.println("发送 POST 请求出现异常！" + e);
        //            e.printStackTrace();
        //        }
        //        //使用finally块来关闭输出流、输入流
        //        finally
        //        {
        //            try
        //            {
        //                if (out != null)
        //                {
        //                    out.close();
        //                }
        //                if (in != null)
        //                {
        //                    in.close();
        //                }
        //            }
        //            catch (IOException ex)
        //            {
        //                ex.printStackTrace();
        //            }
        //        }
        //        return result;

        try
        {
            URL realUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection();
            /**
             * 然后把连接设为输出模式。URLConnection通常作为输入来使用，比如下载一个Web页。
             * 通过把URLConnection设为输出，你可以把数据向你个Web页传送。下面是如何做：
             */
            connection.setRequestMethod("POST");
            connection.addRequestProperty("Content-Type",
                "application/x-www-form-urlencoded; charset=UTF-8");

            connection.setInstanceFollowRedirects(true);
            connection.setDoOutput(true);
            /**
             * 最后，为了得到OutputStream，简单起见，把它约束在Writer并且放入POST信息中，例如： ...
             */
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

            out.write(param); //向页面传递数据。post的关键所在！
            // remember to clean up
            out.flush();
            out.close();
            /**
             * 这样就可以发送一个看起来象这样的POST：
             * POST /jobsearch/jobsearch.cgi HTTP 1.0 ACCEPT:
             * text/plain Content-type: application/x-www-form-urlencoded
             * Content-length: 99 username=bob password=someword
             */
            // 一旦发送成功，用以下方法就可以得到服务器的回应：
            InputStream l_urlStream;
            l_urlStream = connection.getInputStream();
            // 传说中的三层包装阿！
            BufferedReader l_reader = new BufferedReader(new InputStreamReader(l_urlStream,
                "UTF-8"));

            String line;
            while ((line = l_reader.readLine()) != null)
            {
                result += line;
            }

            if (l_reader != null)
            {
                l_reader.close();
            }
            if (l_urlStream != null)
            {
                l_urlStream.close();
            }

            System.out.println(result);

        }
        catch (Exception e)
        {
            e.printStackTrace();
            return result;
        }
        return result;
    }

    @SuppressWarnings("unused")
    private static void trustAllHttpsCertificates()
        throws Exception
    {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    static class miTM implements TrustManager, X509TrustManager
    {
        public java.security.cert.X509Certificate[] getAcceptedIssuers()
        {
            return null;
        }

        public boolean isServerTrusted(java.security.cert.X509Certificate[] certs)
        {
            return true;
        }

        public boolean isClientTrusted(java.security.cert.X509Certificate[] certs)
        {
            return true;
        }

        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
            throws CertificateException
        {
            return;
        }

        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
            throws CertificateException
        {
            return;
        }
    }

}
